﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using DeVetma.admin.classes;
using DeVetma.admin.models.database.metadata;
using DeVetma.admin.models.database;
using DeVetma.admin.models.entities;

namespace DeVetma.admin.models.managers
{
    public sealed class OrderManager : DataManager<Order>
    {
        private Database db = Database.instance();

        public override string ensureKey(Order entity)
        {
            List<Order> orders = getAll();

            int len = (orders.Count < 1 ? 1 : ((int)Math.Log10(orders.Count)) + 2);
            entity.oID = Utilities.randomizeNumericString(len);
            while (orders.Exists(q => q.oID == entity.oID))
                entity.oID = Utilities.randomizeNumericString(len);

            return entity.oID;
        }

        public Order getMemberCart(string mUsername)
        {
            return getOrderMemberStatus(mUsername, (int)Order.OrderStatus.Cart)
                .LastOrDefault();
        }

        public List<Order> getOrderMemberStatus(string mUsername, int status)
        {
            return getByMember(mUsername).Where(q => q.oStatus == status).ensure();
        }

        public bool hasByMemberStatus(string mUsername, int status)
        {
            return getOrderMemberStatus(mUsername, status).Count > 0;
        }

        public bool hasCartAlready(string mUsername)
        {
            return getMemberCart(mUsername) != null;
        }

        public List<Order> getByStatus(int status)
        {
            return getAll().Where(q => q.oStatus == status).ensure();
        }

        public List<Order> getByStatusNot(int status)
        {
            return getAll().Where(q => q.oStatus != status).ensure();
        }

        public List<Order> getByMember(string id)
        {
            return getAll().Where(q => q.mUsername == id).ensure();
        }

        public List<Order> getByMemberNot(string id)
        {
            return getAll().Where(q => q.mUsername != id).ensure();
        }

        public List<Order> getByOrderDate(DateTime date, ComparisonOperatorType opert, 
            DateTime date2)
        {

            switch (opert)
            {
                case ComparisonOperatorType.NotEquals:
                    return getAll().Where(q => q.oDate != date).ensure();

                case ComparisonOperatorType.MoreThan:
                    return getAll().Where(q => q.oDate > date).ensure();

                case ComparisonOperatorType.MoreThanEquals:
                    return getAll().Where(q => q.oDate >= date).ensure();

                case ComparisonOperatorType.LessThan:
                    return getAll().Where(q => q.oDate < date).ensure();

                case ComparisonOperatorType.LessThanEquals:
                    return getAll().Where(q => q.oDate <= date).ensure();

                case ComparisonOperatorType.Between:
                    return getAll().Where(q => q.oDate >= date && q.oDate <= date2).ensure();

                case ComparisonOperatorType.NotBetween:
                    return getAll().Where(q => q.oDate < date || q.oDate > date2).ensure();

                case ComparisonOperatorType.BetweenExclusive:
                    return getAll().Where(q => q.oDate > date && q.oDate < date2).ensure();
               
                case ComparisonOperatorType.OrEquals:
                    return getAll().Where(q => q.oDate == date || q.oDate == date2).ensure();

                case ComparisonOperatorType.OrNotEquals:
                    return getAll().Where(q => q.oDate != date || q.oDate != date2).ensure();

                case ComparisonOperatorType.AndNotEquals:
                    return getAll().Where(q => q.oDate != date && q.oDate != date2).ensure();

                default:
                    return getAll().Where(q => q.oDate == date).ensure();
            }
        }

        public override bool delete(Order entity)
        {
            return entity.delete();
        }

        public override bool deleteAll(Order[] entities, List<Order> failed)
        {
            bool hasFailure = false;

            foreach (var entity in entities)
            {
                if (!entity.delete())
                {
                    if (failed != null)
                        failed.Add(entity);
                }
            }

            return !hasFailure;
        }
    }
}